home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
atpar20.arc
/
ATPARITY.ASM
next >
Wrap
Assembly Source File
|
1985-12-11
|
21KB
|
518 lines
PAGE 80,132
PAGE
TITLE ATPARITY.COM - PC/AT PARITY INTERCEPTOR V2.0
SUBTTL (C) John R. Petrocelli 12/11/85
; 3890 Carman Rd.
; Schenectady, N.Y. 12303
PAGE
;
;
; ATPARITY.COM DETECTS PARITY ERRORS, LOGS THEM TO THE SCREEN AND
; PRINTER, IF AVAILABLE, BEEPS, AND RETURNS TO PROGRAM
; EXECUTION. SYSTEM DOES NOT HALT WHEN THIS PROGRAM IS
; RESIDENT. PARITY ERROR CHECKING IS TERMINATED AFTER
; FIRST ERROR IS DETECTED. THE ERROR MESSAGE INCLUDES
; THE TIME OF THE EVENT.
;
; There is a chance that, if the parity error occurrs in
; a critical program or data, your system will still lock up.
; With the default IBM BIOS Handler you will always hang
; and have to reach for the Big Red Switch Interupt!
;
;
; This Parity Error Handler emulates the standard PC/AT
; Parity Error Handler reporting parity errors to the nearest
; 64k block. Perhaps if an error is occurring just beyond
; the resident utilities the offending bank of 128k chips
; could be swaped with the first bank of 128k chips.
; NOTE --- 128k chips which are actually two 64k chips
; piggybacked are NOT completely pin compatable
; with 64k chips.
;
; VER 2.0 DIFFERENCES
;
; Version 1.0 did not report the failing address. This
; version (2.0) will report the filing 64k block of
; memory if at all possible.
;
;
; DISCLAMER The author makes no waranties with regard to the use of
; this program and assumes no responsibility for lost data.
; One may use this program at his own risk. It has been
; tested as far as possible and performs as specified.
;
; This program may be freely copied and distributed for non
; commercial use and NO CHARGE is to be associated with such
; copying and distribution.
;
; Any suggestions, comments or problems should be fowarded
; to the author.
;
;********************** EQUATES **************************************
BASE_RAM EQU 10H
MFG_PORT EQU 80H
PORT_A EQU 60H
PORT_B EQU 61H
PARITY_ERR EQU 0C0H
READ_8042_INPUT EQU 0C0H
CMOS_PORT EQU 070H
RAM_PAR_OFF EQU 00001100B
RAM_PAR_ON EQU 11110011B
PRTY_CHK EQU 10000000B
IO_CHK EQU 01000000B
STATUS_PORT EQU 64H
OUT_BUF_FULL EQU 01H
INPT_BUF_FULL EQU 02H
DIS_KBD EQU 0ADH
ENA_KBD EQU 0AEH
FF EQU 0CH ;FORM FEED
CR EQU 0DH ;CARRAGE RETURN
LF EQU 0AH ;LINE FEED
BEEP EQU 07H ;BEEP
EOM EQU '$' ;END OF MESSAGE
ASCII_0 EQU '0' ;ASCII CHARACTER 0
ASCII_1 EQU '1' ;ASCII CHARACTER 1
ASCII_2 EQU '2' ;ASCII CHARACTER 2
PRINTER_ACK_OK EQU 00101001B ;PRINTER ACKNOWLEGE OK
AT_ID EQU 0FCH ;AT ID AT FFFF:000E
;XT IS 0FEH
;PC IS 0FFH
;PCjr IS 0FDH
;********************** ADDRESS OF ROM ID ****************************
ROM SEGMENT AT 0FFFFH
ORG 0EH
ROM_ID DB ?
ROM ENDS
;********************** ADDRESS OF INTERRUPT VECTORS *****************
VECTS SEGMENT AT 0H
ORG 2H*4
INT_2 DW ?
VECTS ENDS
;********************** ADDRESS OF BIOS DATA SEGMENT *****************
DATA SEGMENT AT 40H
ORG 13H
MEMORY_SIZE DW ?
ORG 6CH
TIMER_LOW DW ?
TIMER_HIGH DW ?
DATA ENDS
;********************** BEGINNING OF ATPARITY INSTRUCTIONS ***********
CSEG SEGMENT
ASSUME CS:CSEG ;CS POINTS TO CODE SEGMENT
ORG 100H ;NEEDED FOR .COM
START: JMP NMI_NEW
;********************** NMI HANDLER **********************************
NEW_NMI PROC NEAR ;START OF NEW NMI HANDLER
ASSUME DS:DATA ;DS TO POINT TO BIOS DATA AREA IN RAM
CLI ;BE SURE THAT INTERUPTS ARE OFF
;THEY ARE OFF NORMALLY AT THE
;START OF ANY INTERUPT ROUTINE
JMP GO ;JUMP OVER PROGRAM DATA
;---------------------- PROGRAM DATA AREA -----------------------------
;
; LOADED AND COPY_R MESSAGES ARE IN RESIDENT PORTION OF CODE
; SO THAT THEY WILL APPEAR IF THE RESIDENT PROGRAMS ARE SCANNED
; FOR IN RAM
;----------------------------------------------------------------------
LOADED DB "PC/AT PARITY ERROR INTERCEPTOR V2.0 INSTALLED",CR,LF,EOM
COPY_R DB "(C) John R. Petrocelli, Schenectady,N.Y. 12/11/85",CR,LF,EOM
PAR1 DB FF,BEEP,CR,LF,"PARITY ERROR "
PAR1X DB 0,BEEP,CR,LF
PAR_SEG DB 5 DUP("?")," (S) (20 BIT ADDR. 4 HIGHEST ARE SIGNIFICANT)",CR,LF
TIME DB "TIME: ??:??",0DH,0AH
PAROFF DB "PARITY CHECKING WILL BE DISABLED !",CR,LF,BEEP,FF
MSG_LEN DW $-OFFSET PAR1
MFG_SAV DB ? ;MFG_PORT SAVE
CMS_SAV DB ? ;CMOS_PORT SAVE
STA_SAV DB ? ;STATUS_PORT SAVE
PTB_SAV DB ? ;PORT_B SAVE
;---------------------- TEMPORARY PROGRAM STACK ----------------------
STACK DW 50 DUP(?) ;STACK IS 25 WORDS DEEP !
STACK_HI DW $-2 ;POINTER TO END OF STACK
OLD_SS DW ? ;SAVE FOR STACK SEG ON ENTRY
OLD_SP DW ? ;SAVE FOR STACK PTR ON ENTRY
;---------------------- MAIN PROGRAM ---------------------------------
GO: MOV CS:OLD_SS,SS ;SAVE OLD STACK SEGMENT
MOV CS:OLD_SP,SP ;AND STACK POINTER
MOV SP,CS ;POINT TO OUR INTERNAL STACK SEG
MOV SS,SP
MOV SP,CS:STACK_HI ;AND STACK POINTER
PUSH AX ;PUSH ALL GENERAL REGISTERS
PUSH BX ;INTO OUR STACK
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
IN AL,MFG_PORT ;GET NMI COUNT
INC AL ;INCREMENT NMI COUNT BY 1
JMP SHORT $+2 ;I/O DELAY
OUT MFG_PORT,AL ;SAVE NMI COUNT
MOV CS:MFG_SAV,AL ;SAVE MFG_PORT STATUS
IN AL,PORT_B ;GET VALUE IN PORT_B
TEST AL,PARITY_ERR ;IS IT A PARITY ERROR ?
MOV AH,AL ;SAVE STATUS
JNZ NMI_1 ;YES - CONTINUE
JMP D14 ;NO - EXIT
NMI_1:
MOV CS:PTB_SAV,AH ;SAVE PORT_B STATUS
MOV AL,DIS_KBD ;DISABLE KEYBOARD
CALL C8042
IN AL,PORT_A ;FLUSH
MOV AL,READ_8042_INPUT ;GET THE SWITCH SETTINGS
CALL C8042
CALL OBF_42 ;WAIT FOR OUTPUT BUFFER FULL
IN AL,PORT_A ;GET THE SWITCH
OUT MFG_PORT,AL ;SAVE THE SWITCH
MOV DX,DATA ;MAKE DS POINT TO BIOS DATA IN RAM
MOV DS,DX
MOV CS:PAR1X,ASCII_1 ;PUT ASCII 1 IN MESSAGE
TEST AH,40H ;I/O PARITY
JNZ NMI_2 ;YES - CONTINUE
MOV CS:PAR1X,ASCII_2 ;PUT ASCII 2 IN MESSAGE
;MUST BE PLANAR
NMI_2:
IN AL,CMOS_PORT ;GET CURRENT VALUE OF CMOS_PORT
MOV CS:CMS_SAV,AL ;SAVE CMOS_PORT VALUE
JMP SHORT $+2 ;I/O DELAY
IN AL,STATUS_PORT ;GET CURRENT VALUE OF STATUS_PORT
MOV CS:STA_SAV,AL ;SAVE STATUS_PORT VALUE
MOV AL,0FFH ;MASK TRAP
OUT CMOS_PORT,AL
IN AL,PORT_B
JMP SHORT $+2 ;I/O DELAY
OR AL,RAM_PAR_OFF ;TURN OFF NMI FLAG
OUT PORT_B,AL ;TURN OFF NMI
JMP SHORT $+2 ;I/O DELAY
AND AL,RAM_PAR_ON ;TURN ON NMI FLAG
OUT PORT_B,AL ;TURN ON NMI
MOV BX,MEMORY_SIZE ;GET # OF 1K BLOCKS OF MEMORY INSTALLED
CLD ;SET DIRECTION TO INCREMENT
SUB DX,DX ;MAKE DX = 0
NMI_LOOP:
MOV DS,DX ;DS AND ES TO POINT TO
MOV ES,DX ;STARTING SEGMENT FOR SCAN
MOV CX,4000H*2 ;4000h*2 for 64k scan
SUB SI,SI ;SI = 0 START OF SCAN
REP LODSW ;READ MEMORY 1 WORD AT A TIME CX TIMES
;TO REPRODUCE PARITY ERROR IF POSSIBLE
IN AL,PORT_B ;GET PARITY CHECK STATUS
XCHG AL,AH ;SAVE STATUS
CMP DX,4000H ;END OF FIRST 256k ?
JB NMI_3 ;NO - JMP TO TEST RAM PARITY CHECK
CMP DX,8000H ;ABOVE 512k ?
JAE NMI_4 ;NO - JMP TO TEST I/O PARITY CHECK
IN AL,MFG_PORT ;GET SWITCH SETTINGS
TEST AL,BASE_RAM ;CHECK FOR 2ND 256K OF BASE RAM
JZ NMI_4 ;NO - JMP TO TEST I/O PARITY CHECK
NMI_3: TEST AH,PRTY_CHK ;CHECK FOR RAM PARITY CHECK
JMP NMI_5 ;JMP OVER I/O PARITY TEST
NMI_4: TEST AH,IO_CHK ;CHECK FOR I/O PARITY CHECK
NMI_5: JNZ PRT_NMI ;GO PRINT IF ERROR HAPPENED
ADD DX,1000H ;1000h for 64k scan
SUB BX,64D ;64d for 64k scan
JNZ NMI_LOOP ;IF BX NOT 0 THEN CONTINUE SINCE
;WE HAVE NOT FINISHED SCAN AND NO
;PARITY ERROR HAPPENED
JMP PR_NMX ;ELSE PRINT WITHOUT ADDRESS
;????? IS SEGMENT
PRT_NMI:
MOV DX,DS ;DS HAS SEGMENT WHERE ERROR HAPPENED
LEA BX,PAR_SEG ;BX HAS OFFSET IN SEGMENT OF MESSAGE
MOV AH,0 ;SET AH = 0
MOV AL,DH ;SET AL FOR CALL
CALL ASCII_CONVERT ;CALL TO CONVERT AL TO 2 BYTE ASCII
;AND STORE IN MESSAGE AREA
MOV AH,0 ;SET AH = 0
MOV AL,DL ;SET AL FOR CALL
ADD BX,2 ;BX ADVANCED TO NEXT 2 BYTES OF MESSAGE
CALL ASCII_CONVERT ;CALL TO CONVERT AL TO 2 BYTE ASCII
;AND STORE IN MESSAGE AREA
ADD BX,2 ;BX ADVANCED TO NEXT 2 BYTES OF MESSAGE
MOV BYTE PTR CS:[BX],ASCII_0 ;PUT ASCII 0 AT END OF SEGMENT IN
;MESSAGE
PR_NMX:
CALL GET_TIME ;GET TIME FROM BIOS DATA AREA IN RAM
;AND PUT IN MESSAGE AREA
XOR DX,DX ;SET DX TO FIRST PRINTER
MOV AH,2 ;SET AH TO GET PRINTER STATUS
INT 17H ;CALL BIOS TO GET PRINTER STATUS
TEST AH,PRINTER_ACK_OK ;TEST FOR PRINTER RESPONSE
JNZ DISPL ;NO RESPONSE THEN JUST DISPLAY
MOV SI,OFFSET PAR1 ;SI POINTS TO START OF MESSAGE
MOV CX,CS:MSG_LEN ;CX IS NUMBER OF CHARACTERS TO PRINT
PR_LOOP:
MOV AL,CS:[SI] ;CHARACTER TO PRINT IN AL
INC SI ;ADVANCE TO NEXT CHAR
MOV AH,0 ;FUNCTION TO PRINT CHARACTER IN AL
MOV DX,0 ;DX IS PRINTER TO USE
INT 17H ;CALL BIOS TO PRINT CHARACTER
LOOP PR_LOOP ;LOOP FOR CX CHARACTERS
DISPL:
MOV SI,OFFSET PAR1 ;SI POINTS TO START OF MESSAGE
INC SI ;FORM FEED NOT NEEDED SO SKIP
;FIRST CHARACTER
MOV CX,CS:MSG_LEN ;CX IS NUMBER OF CHARACTERS TO PRINT
SUB CX,2 ;FORM FEED NOT NEEDED SO REDUCE
;NUMBER OF CHARACTERS TO PRINT BY 2
DI_LOOP:
MOV AL,CS:[SI] ;CHARACTER TO PRINT IN AL
INC SI ;ADVANCE TO NEXT CHAR
MOV AH,14 ;FUNCTION TO DISPLAY CHARACTER IN AL
MOV BH,0 ;FOREGROUND COLOR TO USE
INT 10H ;CALL BIOS TO DISPLAY CHARACTER IN AL
LOOP DI_LOOP ;LOOP FOR CX CHARACTERS
JMP SHORT $+2 ;I/O DELAY
MOV AL,PTB_SAV ;GET SAVED VALUE OF PORT_B
OR AL,RAM_PAR_OFF ;TURN OFF NMI FLAG
OUT PORT_B,AL ;TURN OFF NMI
JMP SHORT $+2 ;I/O DELAY
MOV AL,ENA_KBD ;LOAD COMND TO ENABLE KEYBOARD
OUT STATUS_PORT,AL ;AND ENABLE THE KEYBOARD
JMP SHORT $+2 ;I/O DELAY
MOV AL,CS:CMS_SAV ;GET SAVED CMOS_PORT VALUE
OUT CMOS_PORT,AL ;RESTORE CMOS_PORT VALUE
JMP SHORT $+2 ;I/O DELAY
MOV AL,CS:STA_SAV ;GET SAVED STATUS_PORT VALUE
OUT STATUS_PORT,AL ;RESTORE STATUS_PORT VALUE
JMP SHORT $+2 ;I/O DELAY
MOV AL,CS:MFG_SAV ;GET SAVED MFG_PORT VALUE
OUT MFG_PORT,AL ;RESTORE MFG_PORT VALUE
JMP SHORT $+2 ;I/O DELAY
JMP EXIT ;JMP TO EXIT
D14:
MOV AL,8FH ;SET AL TO MASK OFF PARITY CHECKING
OUT CMOS_PORT,AL ;DISABLE PARITY CHECKING
JMP SHORT $+2 ;I/O DELAY
MOV AL,0FH ;SET AL TO MASK ON PARITY CHECKING
OUT CMOS_PORT,AL ;ENABLE PARITY CHECKING
JMP SHORT $+2 ;I/O DELAY
EXIT:
POP ES ;RESTORE ALL REGISTERS
POP DS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
MOV SS,CS:OLD_SS ;RESTORE SAVED STACK SEGMENT
MOV SP,CS:OLD_SP ;AND POINTER
IRET ;RETURN FROM INTERUPT ROUTINE
NEW_NMI ENDP ;END OF NMI HANDLER MAIN ROUTINE
;********************** SUBROUTINES **********************************
C8042: ;ISSUE COMMAND TO THE 8042
CLI ;INTERUPTS SHOULD ALREADY BE OFF
OUT STATUS_PORT,AL ;SEND VALUE IN AL TO STATUS_PORT
SUB CX,CX
C42_1: IN AL,STATUS_PORT
TEST AL,INPT_BUF_FULL
LOOPNZ C42_1
RET ;RETURN TO CALLER
OBF_42: ;WAIT FOR 8042 RESPONSE
SUB CX,CX
MOV BL,6
C42_2: IN AL,STATUS_PORT
TEST AL,OUT_BUF_FULL
JNZ C42_3
LOOP C42_2
DEC BL
JNZ C42_2
C42_3: RET ;RETURN TO CALLER
ASCII_CONVERT: ;CONVERT A BYTE IN AL TO ITS
;2 BYTE ASCII EQUIVALENT AND STORE
;IN MESSAGE AREA POINTED TO BY BX
PUSH AX ;SAVE AX
MOV CL,4
SHR AL,CL
CALL CALC ;CALCULATE
MOV BYTE PTR CS:[BX],AL ;STORE FIRST ASCII BYTE IN BX
POP AX ;RESTORE AX
AND AL,0FH
CALL CALC ;CALCULATE
MOV BYTE PTR CS:[BX+1],AL ;STORE SECOND ASCII BYTE IN BX+1
RET ;RETURN TO CALLER
CALC: ;CALCULATE ASCII EQUIVALENT
ADD AL,090H
DAA
ADC AL,040H
DAA
RET ;RETURN TO CALLER
GET_TIME: ;GET THE HOURS AND MINUTES FROM
;BIOS DATA AREA IN RAM
PUSH AX ;SAVE REGISTERS
PUSH BX
PUSH CX
PUSH DX
PUSH DS
MOV DX,DATA ;DS TO POINT FO BIOS DATA AREA IN
MOV DS,DX ;RAM
MOV AX,TIMER_HIGH ;GET HIGH PORTION OF TIMER COUNT
CHECK:
CMP AX,24 ;IS IT GREATER THAN 24
JLE GOOD_TIME ;NO - OK CONTINUE
SUB AX,24 ;YES - SUBTRACT 24 AND
JMP CHECK ;CHECK AGAIN
GOOD_TIME:
AAM ;CHANGE TO HOURS TO ASCII
ADD AX,3030H
LEA BX,TIME ;BX POINTS TO FIRST PART OF TIME
;IN MESSAGE AREA
MOV CS:[BX+6],AH ;HOURS - HIGH INTO MESSAGE AREA
MOV CS:[BX+7],AL ;HOURS - LOW INTO MESSAGE AREA
MOV AX,TIMER_LOW ;GET LOW PORTION OF TIMER COUNT
MOV CX,8 ;ISOLATE MINUTES AND CONVERT TO ASCII
SHR AX,CL
MOV DX,60
MUL DL
SHR AX,CL
AAM
ADD AX,3030H
MOV CS:[BX+9],AH ;MINUTES - HIGH INTO MESSAGE AREA
MOV CS:[BX+10],AL ;MINUTES - LOW INTO MESSAGE AREA
POP DS ;RESTORE ALL SAVED REGISTERS
POP DX
POP CX
POP BX
POP AX
RET ;RETURN TO CALLER
;********************** INSTALL NMI HANDLER **************************
NMI_NEW PROC NEAR ;INSTALL NEW NMI HANDLER
JMP CHECK_AT ;JMP OVER DATA
NO_LOAD DB "PC/AT PARITY ERROR INTERCEPTOR V2.0 >NOT< INSTALLED !",CR,LF,BEEP,EOM
NOT_AT DB "SYSTEM IS NOT A PC/AT !",CR,LF,EOM
CHECK_AT:
ASSUME DS:ROM ;POINT DS TO ROM
MOV AX,ROM ;
MOV DS,AX ;
MOV AL,ROM_ID ;GET MACHINE ID
PUSH CS ;PUSH CS AND
POP DS ;RESTORE DS
CMP AL,AT_ID ;IS MACHINE A PC/AT
JZ INSTALL ;YES - INSTALL NEW NMI HANDLER
;NO - PRINT ERROR MESSAGE AND EXIT
MOV DX,OFFSET NO_LOAD ;DX IS ADDR OF MESSAGE TO PRINT
MOV AH,9 ;DOS FUNCTION TO PRINT
INT 21H ;CALL DOS
MOV DX,OFFSET COPY_R ;DX IS ADDR OF MESSAGE TO PRINT
MOV AH,9 ;DOS FUNCTION TO PRINT
INT 21H ;CALL DOS
MOV DX,OFFSET NOT_AT ;DX IS ADDR OF MESSAGE TO PRINT
MOV AH,9 ;DOS FUNCTION TO PRINT
INT 21H ;CALL DOS
INT 20H ;TERMINATE WITHOUT INSTALLING
INSTALL: ;INSTALL NEW NMI HANDLER
MOV DX,OFFSET LOADED ;DX IS ADDR OF MESSAGE TO PRINT
MOV AH,9 ;DOS FUNCTION TO PRINT
INT 21H ;CALL DOS
MOV DX,OFFSET COPY_R ;DX IS ADDR OF MESSAGE TO PRINT
MOV AH,9 ;DOS FUNCTION TO PRINT
INT 21H ;CALL DOS
ASSUME DS:VECTS ;DS POINTS TO INTERUPT VECTORS
PUSH DS
MOV AX,VECTS
MOV DS,AX
MOV INT_2,OFFSET NEW_NMI ;REPLACE STANDARD NMI HANDLER
MOV INT_2[2],CS ;WITH NEW NMI HANDLER
MOV DX,OFFSET NMI_NEW ;DX POINTS TO END OF RESIDENT CODE+1
INT 27H ;TERMINATE AND STAY RESIDENT
NMI_NEW ENDP
CSEG ENDS
END START ;END OF PROGRAM
;-----------------------------------------------------------------------
;-----------------------------------------------------------------------